module poly_func

    use, intrinsic :: iso_fortran_env, only: rk => real64
    implicit none
    private

    public :: diag, rk

    interface diag
        procedure :: diag_real_rank2, diag_real_rank1
    end interface diag

contains

    !> constructs a vector of the diagonal elements of a matrix <br>
    !> 构建矩阵对角元素的向量
    pure function diag_real_rank2(a) result(v)
        real(rk), intent(in) :: a(:, :)
        real(rk) :: v(min(size(a, 1), size(a, 2)))
        integer :: i

        do concurrent(i=1:size(v))
            v(i) = a(i, i)
        end do

    end function diag_real_rank2

    !> constructs a matrix with the diagonal elements of a vector <br>
    !> 构建向量对角元素的矩阵
    pure function diag_real_rank1(v) result(a)
        real(rk), intent(in) :: v(:)
        real(rk) :: a(size(v), size(v))
        integer :: i, j

        do concurrent(j=1:size(v), i=1:size(v))
            if (i == j) then
                a(i, j) = v(i)
            else
                a(i, j) = 0.0_rk
            end if
        end do

    end function diag_real_rank1

end module poly_func

program main

    use poly_func
    implicit none
                                                ! 1.000E+00, 0.000E+00, 0.000E+00,
    print 100, diag([1.0_rk, 2.0_rk, 3.0_rk])   ! 0.000E+00, 2.000E+00, 0.000E+00,
                                                ! 0.000E+00, 0.000E+00, 3.000E+00
100 format(3(es10.3, :, ','))

end program main
